#ifndef AVCODECSAMPLE_PLAYER_PLAYER_H
#define AVCODECSAMPLE_PLAYER_PLAYER_H

#include <future>
#include <queue>
#include <thread>
#include <bits/alltypes.h>
#include "av_codec_sample_log.h"
#include "dfx/error/av_codec_sample_error.h"
#include "sample_info.h"
#include "demuxer.h"
#include "video_decoder.h"
#include "plugin_manager.h"

class Player {
public:
    Player(){}
    ~Player();
    
    static Player& GetInstance()
    {
        static Player player;
        return player;
    }
    
    void Kill();
    int32_t Init(SampleInfo &sampleInfo);
    int32_t Start();
    int32_t Pause();
    int32_t Seek(int64_t position);
    int32_t Resume();
    int32_t Loop(bool loopFlag);
    int32_t WaitForDone();
    
private:
    void VideoDecInputThread();
    void VideoDecOutputThread();
    void Release();
    void StartRelease();

    std::unique_ptr<VideoDecoder> videoDecoder_ = nullptr;
    std::unique_ptr<Demuxer> demuxer_ = nullptr;
    
    std::mutex mutex_;
    std::atomic<bool> isStarted_ { false };
    std::atomic<bool> isPause_ { false };
    std::atomic<bool> isLoop_ { false };
    std::unique_ptr<std::thread> videoDecInputThread_ = nullptr;
    std::unique_ptr<std::thread> videoDecOutputThread_ = nullptr;
    std::unique_ptr<std::thread> releaseThread_ = nullptr;
    std::condition_variable doneCond_;
    SampleInfo sampleInfo_;
    CodecUserData *videoDecContext_ = nullptr;
    static constexpr int64_t MICROSECOND = 1000000;
    static constexpr int64_t MILLISECONDS = 1000;
};

#endif //AVCODECSAMPLE_PLAYER_PLAYER_H
